package la.iok.hzsvn.lewin.movie.cloud.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import la.iok.hzsvn.lewin.cloud.invoker.service.RestServiceInvoker;
import la.iok.hzsvn.lewin.movie.cloud.entity.*;
import la.iok.hzsvn.lewin.movie.cloud.mapper.UserMapper;
import la.iok.hzsvn.lewin.movie.cloud.model.*;
import la.iok.hzsvn.lewin.movie.cloud.utils.PhoneValidateUtils;
import la.iok.hzsvn.lewin.movie.core.RoleEnum;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.model.QR;
import la.iok.hzsvn.lewin.movie.core.model.SimpleUser;
import la.iok.hzsvn.lewin.movie.core.model.UserVo;
import la.iok.hzsvn.lewin.mybatis.model.PageVo;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.redis.config.RedisKeyProperties;
import la.iok.hzsvn.redis.service.RedisService;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.collection.IdOperators;
import la.iok.hzsvn.share.tools.crypto.Sha1Util;
import la.iok.hzsvn.share.tools.exception.SystemException;
import la.iok.hzsvn.share.utils.ArrayUtils;
import la.iok.hzsvn.share.utils.CollectionUtils;
import la.iok.hzsvn.share.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static la.iok.hzsvn.lewin.movie.core.exception.ErrorCode.*;

@Service
public class UserServiceImpl extends BaseServiceImpl<User,UserMapper,Long> implements UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    private static final String DEFAULT_PWD = Sha1Util.sha1("88888888");
    private static final String DEFAULT_PWD_RAW = "88888888";
    private final OrgUnitService orgUnitService;
    private final RoleService roleService;
    private final UserRoleService userRoleService;
    private final PhoneCodeService phoneCodeService;
    private final QRCodeService qrCodeService;
    private final RoomService roomService;
    private final RestServiceInvoker restServiceInvoker;
    private final LoginRecordService loginRecordService;
    private final RedisService redisService;
    private final RedisKeyProperties redisKey;

    public UserServiceImpl(OrgUnitService orgUnitService,
                           UserMapper userMapper,
                           RoleService roleService,
                           UserRoleService userRoleService,
                           PhoneCodeService phoneCodeService,
                           QRCodeService qrCodeService,
                           RoomService roomService,
                           RestServiceInvoker restServiceInvoker,
                           LoginRecordService loginRecordService,
                           RedisService redisService,
                           RedisKeyProperties redisKey) {
        super((userMapper));
        this.orgUnitService = orgUnitService;
        this.roleService = roleService;
        this.userRoleService = userRoleService;
        this.phoneCodeService = phoneCodeService;
        this.qrCodeService = qrCodeService;
        this.roomService = roomService;
        this.restServiceInvoker = restServiceInvoker;
        this.loginRecordService = loginRecordService;
        this.redisService = redisService;
        this.redisKey = redisKey;
    }

    @Transactional
    @Override
    public Long save(@Nullable Token token, UserParam userParam) {
        PHONE_NUMBER_ERROR.assertNotBlank(userParam.getPhoneNumber());
        PHONE_NUMBER_ERROR.assertTrue(PhoneValidateUtils.validatePhoneNumber(userParam.getPhoneNumber()));
        String password = PASSWORD_EMPTY_ERROR.assertNotBlank(userParam.getPassword());
        if(password.length() != 40){
            PASSWORD_INVALID.assertTrue(password.matches("[0-9a-zA-Z~!@#$^&+-]{8,16}"));
        }
        if(userParam.getOrgUnitId() != null && userParam.getOrgUnitId() == -1L){
            //玩家注册,只能注册玩家
            ROLE_NOT_EXIST.assertEqual(RoleEnum.Player.name(),userParam.getRole(),userParam.getRole());
        }else{
            OrgUnit orgUnit = orgUnitService.select(userParam.getOrgUnitId());
            ORG_UNIT_NOT_EXIST.assertNotNull(orgUnit,userParam.getOrgUnitId());
        }
        if(token != null){
            //管理员添加用户,验证管理员权限
            validateAddUser(token, userParam.getRole(), userParam.getOrgUnitId());
        }else{
            //用户自己注册,验证手机验证码
            PhoneCode phoneCode = phoneCodeService.loadPhoneCode(userParam.getPhoneNumber());
            PHONE_CODE_ERROR.assertEqual(phoneCode.getCode(),userParam.getCode());
            ORG_UNIT_ACCESS_DENIED.assertEqual(phoneCode.getOrgUnitId(),userParam.getOrgUnitId(),userParam.getOrgUnitId());
        }
        return doSave(userParam, password, SimpleUser.REG_CHANNEL_OFFICIAL);
    }

    private Long doSave(UserParam userParam, String password, Integer channel) {
        Role r = roleService.select(userParam.getRole());
        ROLE_NOT_EXIST.assertNotNull(r, userParam.getRole());
        ROLE_NOT_EXIST.assertFalse(r.admin(), userParam.getRole());

        User user = select(userParam.getPhoneNumber());
        if(user == null){
            user = new User();
            user.setPhoneNumber(userParam.getPhoneNumber());
            user.setOrgUnitId(userParam.getOrgUnitId());
            user.setPassword(password.length() !=40?Sha1Util.sha1(password): password);
            user.setRegChannel(channel);
            user.setGender(0);
            mapper.insertSelective(user);
        }
        UserRole userRole = userRoleService.select(user.getId(),r.getId(), userParam.getOrgUnitId());
        if(userRole == null){
            userRoleService.save(new UserRole(user.getId(),r.getId(), userParam.getOrgUnitId()));
        }
        return user.getId();
    }

    /**
     * 验证是否有增加用户到组织的权限
     * @param token 操作用户
     * @param role 用户的角色
     * @param orgUnitId 添加到的目标组织id
     */
    private void validateAddUser(Token token, String role, Long orgUnitId) {
        ORG_UNIT_ACCESS_DENIED.assertTrue(token.hasAnyAuthority(RoleEnum.Admin,RoleEnum.Manager,RoleEnum.ShopManager), orgUnitId);
        if(token.hasAuthority(RoleEnum.Admin)){
            //超级管理员都可以
        }else if(token.hasAuthority(RoleEnum.Manager)){
            //最高是管理员权限,验证组织是不是在自己控制权限内
            List<Long> orgUnitIds = new ArrayList<>(orgUnitService.childOrgUnitIds(token.getOrgUnitId()));
            orgUnitIds.add(token.getOrgUnitId());
            ORG_UNIT_ACCESS_DENIED.assertTrue(orgUnitIds.contains(orgUnitId), orgUnitId);
            //管理员不能在自己的组织中创建管理员,但是可以在下级组织中创建管理员
            if(RoleEnum.Manager.name().equals(role)){
                ROLE_NOT_EXIST.assertNotEquals(orgUnitId,token.getOrgUnitId(),role);
            }
        }else{
            //店长,只能添加自己店铺的用户
            ORG_UNIT_ACCESS_DENIED.assertEqual(orgUnitId, token.getOrgUnitId(), orgUnitId);
            //店长不能创建工程人员
            ROLE_NOT_EXIST.assertNotEquals(RoleEnum.Manager.name(), role, role);
            //店长不能创建店长
            ROLE_NOT_EXIST.assertNotEquals(RoleEnum.ShopManager.name(), role, role);
        }
    }

    @Transactional
    @Override
    public Long save(UserParam userParam) {
        return save(null,userParam);
    }
    @Transactional
    @Override
    public Long save(UserLoginParam param) {
        //不存在的用户,需要注册,根据手机验证码查找到注册信息
        UserParam userParam = new UserParam();
        userParam.setPhoneNumber(param.getPhoneNumber());
        userParam.setCode(param.getCode());
        userParam.setRole(RoleEnum.Player.name());
        userParam.setPassword(StringUtils.isBlank(param.getPassword())?DEFAULT_PWD_RAW:param.getPassword());
        userParam.setOrgUnitId(-1L);
        return save(userParam);
    }
    @Transactional
    @Override
    public Long qrCodeSave(UserParam userParam) {
        SCAN_QR_CODE_2_REGISTER.assertNotBlank(userParam.getUuid());
        QR qr = qrCodeService.qrCode(userParam.getUuid());
        if(qr.typeRoom()){
            Room room = roomService.select(qr.getId());
            ROOM_NOT_EXIST.assertNotNull(room,qr.getId());
            userParam.setOrgUnitId(room.getOrgUnitId());
        }else if(qr.typeOrgUnit()){
            userParam.setOrgUnitId(qr.getId());
        }else if(qr.typePlayRecord()){
            userParam.setOrgUnitId(-1L);
        }
        return save(null,userParam);
    }

    @Transactional
    @Override
    public Long wxSave(String phoneNumber) {
        PHONE_NUMBER_ERROR.assertNotBlank(phoneNumber);
        PHONE_NUMBER_ERROR.assertTrue(PhoneValidateUtils.validatePhoneNumber(phoneNumber));
        UserParam param = new UserParam();
        param.setPhoneNumber(phoneNumber);
        param.setRole(RoleEnum.Player.name());
        param.setOrgUnitId(-1L);
        return doSave(param,"",SimpleUser.REG_CHANNEL_WX_MINI);
    }

    @Nullable
    @Override
    public User select(@Nullable String phoneNumber) {
        if(StringUtils.isBlank(phoneNumber))
            return null;
        return mapper.selectByPhoneNumber(phoneNumber);
    }

    @Transactional
    public int delete(@Nullable Long id){
        if(id == null){
            return 0;
        }
        userRoleService.delete("userId",id);
        return mapper.deleteById(id);
    }

    @Override
    @Nullable
    public UserVo po2vo(@Nullable User user) {
        if(user == null){
            return null;
        }
        return po2vo(user,orgUnitService.list(Collections.singleton(user.getOrgUnitId())),
                userRoleService.listByProperty("userId",user.getId()),roleService.selectAll());
    }

    @Override
    public PageVo<UserVo> page(int page, int limit, Token token, Long orgUnitId, String phoneNumber) {
        Page<User> list;
        boolean removePhone = false;
        if(token.hasAuthority(RoleEnum.Admin)){
            list = PageHelper.startPage(page,limit);
            if(orgUnitId != null){
                mapper.list(Collections.singleton(orgUnitId),phoneNumber);
            }else{
                mapper.list(null,phoneNumber);
            }
        }else{
            //只查询用户管理的组织及其下组织的用户
            Set<Long> orgUnitIds = new HashSet<>(orgUnitService.childOrgUnitIds(token.getOrgUnitId()));
            orgUnitIds.add(token.getOrgUnitId());

            if(orgUnitId != null && orgUnitId > 0){
                if(orgUnitIds.contains(orgUnitId)){
                    orgUnitIds = Collections.singleton(orgUnitId);
                }else{
                    return new PageVo<>(limit,page);
                }
            }
            if(orgUnitIds.isEmpty()){
                return new PageVo<>(limit,page);
            }
            list = PageHelper.startPage(page,limit);
            mapper.list(orgUnitIds,phoneNumber);
            if(!token.hasAuthority(RoleEnum.Manager)){
                removePhone = true;
            }
        }
        List<UserVo> data = po2vo(list);
        if(removePhone){
            data.forEach(vo->vo.setPhoneNumber(null));
        }
        PageVo<UserVo> pageVo = new PageVo<>();
        pageVo.setPages(list.getPages());
        pageVo.setTotal(list.getTotal());
        pageVo.setCurrent(list.getPageNum());
        pageVo.setSize(list.getPageSize());
        pageVo.setRecords(data);
        return pageVo;
    }

    @Transactional
    @Override
    public void modify(@NotNull Token token, @NotNull Long id, @NotNull UserModifyParam user) {
        if(StringUtils.isNotBlank(user.getPhoneNumber())){
            PHONE_NUMBER_ERROR.assertTrue(PhoneValidateUtils.validatePhoneNumber(user.getPhoneNumber()));
        }
        validateModifyAuthority(token, id, user.getOrgUnitId());
        try{
            mapper.update(id,user.getPhoneNumber(),null,user.getOrgUnitId());
        } catch (DuplicateKeyException e){
            logger.error("用户{}修改失败",id,e);
            PHONE_NUMBER_REGISTERED.fail(user.getPhoneNumber());
        }
    }

    /**
     * 验证是否有修改用户信息的权限
     * @param token 操作用户
     * @param id 待修改用户id
     * @param targetOrgUnitId 如果修改用户组织.那就是目标组织的id.不修改组织可以传null
     */
    private void validateModifyAuthority(Token token, Long id, Long targetOrgUnitId) {
        ADMIN_DENIED.assertTrue(token.hasAnyAuthority(RoleEnum.Admin,RoleEnum.Manager,RoleEnum.ShopManager));
        if(!token.hasAuthority(RoleEnum.Admin)){
            if(token.hasAuthority(RoleEnum.Manager)){
                //管理员只能修改自己所管理的组织下的用户
                User entity = select(id);
                INVALID_USER.assertNotNull(entity);
                List<Long> tokenOrgUnits = new ArrayList<>(orgUnitService.childOrgUnitIds(token.getOrgUnitId()));
                tokenOrgUnits.add(token.getOrgUnitId());
                List<UserRole> userRoles = userRoleService.userRoles(id).stream().filter(ur->tokenOrgUnits.contains(ur.getOrgUnitId())).collect(Collectors.toList());
                ORG_UNIT_ACCESS_DENIED.assertTrue(userRoles.size() > 0,()->new Object[]{entity.getPhoneNumber()+"所属组织"});
                if(targetOrgUnitId != null){
                    //目标组织也应该是可以管理的
                    ORG_UNIT_ACCESS_DENIED.assertTrue(tokenOrgUnits.contains(targetOrgUnitId),targetOrgUnitId);
                }
            }else{
                //店长只能修改本店的用户
                User entity = select(id);
                INVALID_USER.assertNotNull(entity);
                List<UserRole> userRoles = userRoleService.userRoles(id).stream().filter(ur->Objects.equals(token.getOrgUnitId(),ur.getOrgUnitId())).collect(Collectors.toList());
                ORG_UNIT_ACCESS_DENIED.assertTrue(userRoles.size() > 0,()->new Object[]{entity.getPhoneNumber()+"所属组织"});
                if(targetOrgUnitId != null){
                    ORG_UNIT_ACCESS_DENIED.assertEqual(targetOrgUnitId, token.getOrgUnitId(),targetOrgUnitId);
                }
            }
        }
    }

    @Override
    public void resetPwd(@NotNull Token token, @NotNull Long id) {
        //validateModifyAuthority(token,id,null);
        token.validAnyAuthority(RoleEnum.Admin);
        mapper.update(id,null,DEFAULT_PWD,null);
    }

    @Override
    public void current(@NotNull Token token, @Nullable Long orgUnitId) {
        OrgUnit orgUnit = orgUnitService.select(orgUnitId);
        ORG_UNIT_NOT_EXIST.assertNotNull(orgUnit,orgUnitId);
        List<UserRole> list = userRoleService.userRoles(token.getUserId());
        UserRole userRole = list.stream().filter(ur->Objects.equals(ur.getOrgUnitId(),orgUnitId)).findFirst().orElse(null);
        PROPERTY_CHECK_ERROR.assertNotNull(userRole,"组织","用户未加入组织");
        update(token.getUserId(),"orgUnitId",orgUnitId);
    }

    @Override
    public void invite(@NotNull Token token, @Nullable String phoneNumber, @Nullable String role) {
        PHONE_NUMBER_ERROR.assertNotBlank(phoneNumber);
        User user = select(phoneNumber);
        if(user == null){
            UserParam param =new UserParam();
            param.setPhoneNumber(phoneNumber);
            param.setPassword(DEFAULT_PWD_RAW);
            param.setRole(role);
            param.setOrgUnitId(token.getOrgUnitId());
            save(token,param);
        }else{
            Role r = roleService.select(role);
            ROLE_NOT_EXIST.assertNotNull(r,role);
            ROLE_NOT_EXIST.assertFalse(r.admin(),role);
            OrgUnit orgUnit = orgUnitService.select(token.getOrgUnitId());
            ORG_UNIT_NOT_EXIST.assertNotNull(orgUnit,token.getOrgUnitId());
            validateAddUser(token,role, orgUnit.getId());
            UserRole userRole = userRoleService.select(user.getId(),r.getId(),token.getOrgUnitId());
            if(userRole == null){
                userRoleService.save(new UserRole(user.getId(),r.getId(),token.getOrgUnitId()));
            }
        }
    }

    @Override
    public void remove(@NotNull Token token,@Nullable Long userRoleId) {
        UserRole userRole = userRoleService.select(userRoleId);
        RECORD_NOT_EXIST.assertNotNull(userRole,userRoleId);
        Role role = roleService.select(userRole.getRoleId());
        ROLE_NOT_EXIST.assertNotNull(role,userRole.getRoleId());
        ROLE_NOT_EXIST.assertFalse(role.admin(),role.getName());
        OrgUnit orgUnit = orgUnitService.select(userRole.getOrgUnitId());
        ORG_UNIT_NOT_EXIST.assertNotNull(orgUnit,userRole.getOrgUnitId());
        validateAddUser(token,role.getName(), orgUnit.getId());
        userRoleService.delete(userRoleId);
    }

    @Override
    public void modifyAccount(@NotNull Token token, @NotNull AccountModifyParam account) {
        String phoneNumber = PHONE_NUMBER_ERROR.assertNotBlank(account.getNewUsername());
        PHONE_NUMBER_ERROR.assertTrue(PhoneValidateUtils.validatePhoneNumber(phoneNumber));
        //验证手机验证码
        PhoneCode phoneCode = phoneCodeService.loadPhoneCode(phoneNumber);
        PHONE_CODE_ERROR.assertEqual(phoneCode.getCode(),account.getPhoneCode());
        ORG_UNIT_ACCESS_DENIED.assertEqual(phoneCode.getOrgUnitId(),token.getOrgUnitId(),phoneCode.getOrgUnitId());

        User user = select(token.getUserId());
        INVALID_USER.assertNotNull(user);
        String password = PASSWORD_EMPTY_ERROR.assertNotBlank(account.getSourcePassword());
        USERNAME_OR_PASSWORD_ERROR.assertEqual(password,user.getPassword());
        try{
            update(token.getUserId(),"phoneNumber",phoneNumber);
        }catch (DuplicateKeyException e){
            PHONE_NUMBER_REGISTERED.fail(phoneNumber);
        }
    }

    @Override
    public void modifyPassword(@NotNull Token token, @NotNull PasswordModifyParam param) {
        String newPassword = PASSWORD_EMPTY_ERROR.assertNotBlank(param.getNewPassword());
        String sourcePwd = PASSWORD_EMPTY_ERROR.assertNotBlank(param.getSourcePassword());
        User user = select(token.getUserId());
        INVALID_USER.assertNotNull(user);
        USERNAME_OR_PASSWORD_ERROR.assertEqual(sourcePwd,user.getPassword());
        update(token.getUserId(),"password",newPassword);
    }

    @Override
    public void modifyPassword(@NotNull ForgotSetPasswordParam param) {
        String newPassword = PASSWORD_EMPTY_ERROR.assertNotBlank(param.getNewPassword());
        //验证手机验证码
        String phoneNumber = PHONE_NUMBER_ERROR.assertNotBlank(param.getPhoneNumber());
        PhoneCode phoneCode = phoneCodeService.loadPhoneCode(phoneNumber);
        PHONE_CODE_ERROR.assertEqual(phoneCode.getCode(),param.getCode());
        User user = select(phoneNumber);
        INVALID_USER.assertNotNull(user);
        update(user.getId(),"password",newPassword.length() !=40?Sha1Util.sha1(newPassword):newPassword);
    }

    private List<UserVo> po2vo(List<User> users){
        if(CollectionUtils.isEmpty(users)){
            return Collections.emptyList();
        }
        Set<Long> orgUnitIds = users.stream().map(User::getOrgUnitId).collect(Collectors.toSet());
        List<OrgUnit> orgUnits = orgUnitService.list(orgUnitIds);
        List<UserRole> userRoles = userRoleService.userRoles(users.stream().map(User::getId).collect(Collectors.toSet()));
        List<Role> roles = roleService.selectAll();
        return users.stream().map(item-> po2vo(item, orgUnits, userRoles, roles)).collect(Collectors.toList());
    }

    private UserVo po2vo(@NotNull User user, @Nullable List<OrgUnit> orgUnits, @NotNull @NotNullElement List<UserRole> userRoles, @NotNull @NotNullElement List<Role> roles) {
        UserVo vo = new UserVo();
        BeanUtils.copyProperties(user,vo);
        OrgUnit orgUnit = IdOperators.find(orgUnits, user.getOrgUnitId());
        if(orgUnit != null){
            vo.setOrgUnitName(orgUnit.getName());
            vo.setOrgUnitType(orgUnit.getType());
            vo.setHideCloudMovie(orgUnit.getHideCloudMovie());
        }
        Set<Long> roleIds = userRoles.stream().filter(ur->Objects.equals(user.getId(),ur.getUserId())
                && Objects.equals(user.getOrgUnitId(),ur.getOrgUnitId())).map(UserRole::getRoleId).collect(Collectors.toSet());
        vo.setRoles(roles.stream().filter(r->roleIds.contains(r.getId())).map(Role::getName).collect(Collectors.toList()));
        return vo;
    }

    @Override
    public TokenInfo token(UserLoginParam param) {
        String phoneNumber = PHONE_NUMBER_ERROR.assertNotBlank(param.getPhoneNumber());
        PHONE_NUMBER_ERROR.assertTrue(PhoneValidateUtils.validatePhoneNumber(phoneNumber));
        if(StringUtils.isBlank(param.getPassword())){
            PhoneCode phoneCode = phoneCodeService.loadPhoneCode(phoneNumber);
            PHONE_CODE_ERROR.assertEqual(phoneCode.getCode(), param.getCode());
        }
        User user = select(phoneNumber);
        if(user == null){
            Long id = save(param);
            user = select(id);
        }
        USERNAME_OR_PASSWORD_ERROR.assertNotNull(user);
        INVALID_USER.assertEqual(UserVo.STATUS_NORMAL, user.getDisabled());
        if(StringUtils.isNotBlank(param.getPassword())){
            String pwd = param.getPassword().trim();
            if(pwd.length() != 40){
                //临时处理,前端可能已经加密为sha1码了
                pwd = Sha1Util.sha1(pwd);
            }
            //如果是空字符串的sha1码,那也不能登录（这种可能是小程序注册的用户，小程序注册用户默认密码为空,服务端对空字符串加密保存
            MINI_USER_LOGIN_EMPTY_PWD.assertNotEquals(Sha1Util.sha1(""),pwd);
            USERNAME_OR_PASSWORD_ERROR.assertEqual(user.getPassword(),pwd);
        }
        if(user.getOrgUnitId() != null && user.getOrgUnitId() > 0){
            if(userRoleService.hasOnlyAuthority(user.getId(),user.getOrgUnitId(),RoleEnum.DM)){
                //只有DM角色
                if(param.clientWebBrowser()){
                    throw new SystemException("主持人请在PAD端登录");
                }
            }
        }

        Map<String,String> params = new HashMap<>();
        params.put("username",phoneNumber);
        params.put("password",user.getPassword());
        params.put("grantType","password");
        params.put("clientId","lewin");
        params.put("clientSecret","lwp2wd");
        TokenInfo token = restServiceInvoker.postForObject("authserver","/oauth/token?username={username}&password={password}&grant_type={grantType}&client_id={clientId}&client_secret={clientSecret}",null, TokenInfo.class,params);
        loginRecordService.save(user, param.getDevice(),StringUtils.isBlank(param.getPassword())?2:1);
        return token;
    }

    @Override
    public List<AccessCount> todayActiveUser() {
        Calendar now = Calendar.getInstance();
        int hour = now.get(Calendar.HOUR_OF_DAY);
        int day = now.get(Calendar.DATE);
        List<AccessCount> list = new LinkedList<>();
        for(int i = 0; i <= hour; ++i){
            String key = redisKey.key("gw","ol","un",String.format("%02d_%02d",day,i));
            long count = redisService.setsSize(key);
            AccessCount ac = new AccessCount();
            ac.setCount(count);
            ac.setHour(String.format("%02d",i));
            list.add(ac);
        }
        return list;
    }

    @Override
    public void nickname(@NotNull Token token, @Nullable String nickname,@Nullable int gender) {

            if(gender!=0)
            {
                if(gender==1 || gender==2) {
                    User user = select(token.getUserId());
                    INVALID_USER.assertNotNull(user);
                    update(token.getUserId(), "gender", gender);
                }
            }
            else {
            nickname = PROPERTY_CHECK_ERROR.assertNotBlank(nickname, "修改信息", "不能为空");
        }
        if(nickname!=null) {
            nickname = PROPERTY_CHECK_ERROR.assertNotBlank(nickname, "修改信息", "不能为空");
            User user = select(token.getUserId());
            INVALID_USER.assertNotNull(user);
            update(token.getUserId(), "nickname", nickname);
        }

    }

    @Override
    public void disable(@NotNull Token token, @Nullable Long id) {
        token.validAnyAuthority(RoleEnum.Admin);
        User user = select(id);
        INVALID_USER.assertNotNull(user);
        update(id,"disabled",UserVo.STATUS_DISABLED);
    }

    @Override
    public void enable(@NotNull Token token, @Nullable Long id) {
        token.validAnyAuthority(RoleEnum.Admin);
        User user = select(id);
        INVALID_USER.assertNotNull(user);
        update(id,"disabled",UserVo.STATUS_NORMAL);
    }

    @NotNull
    @NotNullElement
    @Override
    public List<SimpleUser> users(@Nullable Long[] ids) {
        List<User> list = ArrayUtils.runWhenNotEmptyWithTrimNullToSet(ids,Collections::emptyList,set->listInProperty("id",set));
        return list.stream().map(u->{
            SimpleUser vo =new SimpleUser();
            BeanUtils.copyProperties(u,vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public User selectUser(Long UserId) {
        return mapper.selectUser(UserId);
    }
}
